import os
import numpy as np
import numpy.linalg as la

PATH = os.path.dirname(os.path.abspath(__file__))  # 当前文件夹路径
DATA = os.path.join(PATH, 'data')  # 数据文件夹

def readDataSet(file):
    data = []
    try:
        with open(file) as fopen:
            line = fopen.readline()
            while line:
                line = line.strip('\n')
                line = [float(item.strip()) for item in line.split(',')]
                data.append(line)
                line = fopen.readline()
            return np.array(data)
    except Exception as e:
        print("error: ", e)


def SVD(dataM, k=30):
    # 奇异值分解
    h, w = dataM.shape[:2]
    U, S, Vt = la.svd(dataM)  # 奇异值分解

    S1 = np.diag(S[:k], 0)  # 奇异值矩阵
    U1 = np.zeros((h, k), float)
    Vt1 = np.zeros((k, w), float)
    U1[:, :] = U[:, :k]
    Vt1[:, :] = Vt[:k, :]
    return Vt1


def pca(dataM):
    """
    主成分分析PCA--数据矩阵的奇异值分解
    :param dataM:
    :return:
    """
    row, col = dataM.shape
    means = np.mean(dataM, axis=0)
    variances = np.var(dataM, axis=0)
    dataM = (dataM - means) / np.sqrt(variances)  # 标准化变量

    print("标准化变量后, 维度(%d, %d): \n" % dataM.shape)
    print(dataM)

    new_dataM = dataM.T / np.sqrt(col - 1)
    Vt = SVD(new_dataM, k=10)

    print("PCA结果, 维度(%d, %d): \n" % np.dot(Vt, dataM).shape)

    print(np.dot(Vt, dataM))


if __name__ == '__main__':

    dataM = readDataSet(os.path.join(DATA, 'SPECTF.data'))

    pca(dataM.T)